﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WinFormsApp1.RelationForms
{
    internal class FormRelationOneTableExporter
    {
        public string SaveFileName { get; internal set; }
        public DataTable? KeyIDDataTable { get; internal set; }
        public DataTable? SourceDataTable { get; internal set; }
        public string DataTableName { get; internal set; }
        public string EntityAAliasName { get; internal set; }
        public string EntityBAliasName { get; internal set; }
        public string ConnectionName { get; internal set; }

        public void SaveFile()
        {
            Neo4JJSON neo4JJSON = new Neo4JJSON();
            var res1 = new Neo4JData();
            neo4JJSON.results.Add(res1);

            var gd = new Neo4JGraphData();
            res1.data = new List<Neo4JGraphData>() { gd };
            gd.graph = new Neo4JGraph();

            var column1 = DataTableName + KeyIDDataTable.Columns[0].ColumnName;
            var column2 = DataTableName + KeyIDDataTable.Columns[1].ColumnName;
            res1.columns.Add(column1);
            res1.columns.Add(column2);

            for (var i = 0; i < KeyIDDataTable.Rows.Count; i++)
            {
                //全部数据的内容
                var rowProperity = GetRowProperity(SourceDataTable, i);

                var id1 = KeyIDDataTable.Rows[i][0].ToString();
                var id2= KeyIDDataTable.Rows[i][1].ToString();
                gd.graph.nodes.Add(new Neo4JNode()
                {
                    id = id1,
                    labels = new List<string>() { column1 },
                    properties = GetEntityProperity( rowProperity,0, id1)
                });
                gd.graph.nodes.Add(new Neo4JNode()
                {
                    id = id2,
                    labels = new List<string>() { column2 },
                    properties = GetEntityProperity(rowProperity,1,id2)
                });

                gd.graph.relationships.Add(new Neo4JRelationship()
                {
                    id = Math.Abs((id1+id2).GetHashCode()).ToString(),
                    startNode = id1,
                    endNode = id2,
                    type = ConnectionName
                });
            }
            res1.columns = res1.columns.Distinct().ToList();

            var str = JsonConvert.SerializeObject(neo4JJSON);
            File.WriteAllText(SaveFileName, str);
        }

        private Dictionary<string,string> GetRowProperity(DataTable dt,int rowIndex)
        {
            Dictionary<string, string> dir = new Dictionary<string, string>();
            for (var i = 0; i < dt.Columns.Count; i++)
            {
                dir.Add(dt.Columns[i].ColumnName, dt.Rows[rowIndex][i].ToString());
            }
            return dir;
        }

        private Dictionary<string, string> GetEntityProperity(Dictionary<string, string> dir, int index,string defaultName)
        {
            Dictionary<string, string> cloneDir = new Dictionary<string, string>();

            string formatNameString = "";
            if (index == 0)
            {
                formatNameString = EntityAAliasName;
            }
            else
            {
                formatNameString = EntityBAliasName;
            }

            if (HasFormatStr(formatNameString) ==false)
            {
                cloneDir.Add("name", defaultName);
                return cloneDir;
            }
                
            foreach(var key in dir.Keys)
            {
                cloneDir.Add(key, dir[key]);
            }
            
            if (string.IsNullOrEmpty(formatNameString) == false)
            {
                string entityName = GetFormatEntityName(dir,formatNameString);
                if (cloneDir.ContainsKey("name") == false)
                {
                    cloneDir.Add("name", entityName);
                }
                else
                {
                    cloneDir["name"] = entityName;
                }
            }

            if (cloneDir.ContainsKey("name") == false)
                cloneDir.Add("name", defaultName);
            return cloneDir;
        }
        private bool HasFormatStr(string formatStr)
        {
            if (formatStr.IndexOf('{') >= 0) { return true; }
            if (formatStr.IndexOf('#') >= 0) { return true; }
            return false;
        }
        public static string GetFormatEntityName(Dictionary<string, string> entityProperities, string formatStr)
        {
            if (formatStr.IndexOf('{') >= 0)
            {
                while (true)
                {
                    var t1 = formatStr.IndexOf('{');
                    if (t1 == -1)
                    {
                        return formatStr;
                    }
                    else
                    {
                        var t2 = formatStr.IndexOf('}', t1);
                        var key = formatStr.Substring(t1 + 1, t2 - t1 - 1);
                        var fKey = entityProperities.ContainsKey(key) ? entityProperities[key] : "";
                        formatStr = formatStr.Substring(0, t1) + fKey + formatStr.Substring(t2 + 1);
                    }
                }
            }
            if (formatStr.IndexOf('#') >= 0)
            {
                EntityNaming entityNaming = new EntityNaming(formatStr);
                return entityNaming.Prefix + (entityProperities.ContainsKey(entityNaming.ColumnName) ?
                    entityProperities[entityNaming.ColumnName] : "") + entityNaming.Postfix;
            }
            return formatStr;
        }
    }
}
